import {
  Component,
  OnInit,
  ViewEncapsulation,
  ChangeDetectionStrategy,
  ChangeDetectorRef,
  Output,
  EventEmitter
} from '@angular/core';

@Component({
  selector: 'seed-calendar',
  templateUrl: './calendar.component.html',
  styleUrls: ['./calendar.component.scss'],
  encapsulation: ViewEncapsulation.None,
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class CalendarComponent implements OnInit {
  public el: any;
  public tabIndex: number;
  public valueTabIndex: number;
  public date: Date;
  public value: any;
  public yearNode: any;
  public monthNode: any;
  @Output() confirm: EventEmitter<any> = new EventEmitter();
  @Output() cancel: EventEmitter<any> = new EventEmitter();

  constructor(private cdRef: ChangeDetectorRef) {
  }

  initial() {
    this.el = document.querySelector('.date-range-picker');
    this.tabIndex = 0;
    this.valueTabIndex = null;
    this.date = new Date();
    this.value = new Array(2);
    this.yearNode = this.el.querySelector('.date-range-picker__year span');
    this.monthNode = this.el.querySelector('.date-range-picker__month span');
    this.yearNode.innerHTML = this.date.getFullYear();
    this.monthNode.innerHTML = this.date.getMonth() + 1;
    this.bindEvent();
    this.render();
  }

  toArray(nodes) {
    return Array.prototype.slice.call(nodes);
  }

  changeMonth(value) {
    this.date.setMonth(value);
    this.render();
  }

  changeYear(value) {
    this.date.setFullYear(value);
    this.render();
  }

  setValue(value) {
    this.el.querySelector('.date-range-picker__confirm').disabled = value[0] ? false : true;
    this.value = value;
    if (value[0] && value[1] && value[1].getTime() > value[0].getTime()) {
      this.valueTabIndex = this.tabIndex;
    } else {
      this.valueTabIndex = null;
    }
  }

  parseValue(value) {
    return value.split('-').map(function (item) {
      return new Date(parseInt(item, 10));
    });
  }

  getLastDate(year, month) {
    if (month === 11) {
      year++;
      month = 0;
    } else {
      month++;
    }
    return new Date(year, month, 0);
  }

  bindEvent() {
    this.el.querySelector('.date-range-picker__calendar').addEventListener('click', this.handleChange.bind(this), false);
  }

  handleTab(index, e) {
    if (this.tabIndex !== index) {
      this.tabIndex = index;
      e.target.parentNode.querySelector('.active').classList.remove('active');
      e.target.classList.add('active');
      this.render();
    }
  }

  handleChangeYear(type, e) {
    let year = this.date.getFullYear() + (type === 0 ? -1 : 1);
    if (year <= 1990) {
      year = 1990;
    }
    this.yearNode.innerHTML = year;
    this.changeYear(year);
  }

  handleChangeMonth(type, e) {
    const buttons = e.target.parentNode.querySelectorAll('button');
    let month = this.date.getMonth() + (type === 0 ? -1 : 1);
    if (month <= 0) {
      month = 0;
    }
    buttons[1].disabled = month === 11;
    buttons[0].disabled = month === 0;
    this.date.setMonth(month);
    this.monthNode.innerHTML = month + 1;
    this.changeMonth(month);
  }

  removeActive(node) {

    const  list = node.querySelectorAll('.active, .start, .end');
    for (let i = list.length - 1; i >= 0; i--) {
      list[i].classList.remove('active', 'start', 'end');
    }
    /*this.toArray(node.querySelectorAll('.active')).forEach(function (each) {
      each.classList.remove('active');
    });
    this.toArray(node.querySelectorAll('.start')).forEach(function (each) {
      each.classList.remove('start');
    });
    this.toArray(node.querySelectorAll('.end')).forEach(function (each) {
      each.classList.remove('end');
    });*/
  }
  handleChange(e) {
    if (!e.target.dataset.value) {
      return;
    }
    if (this.tabIndex === 0) {
      if ((this.value[0] && this.value[1]) || (!this.value[0] && !this.value[1])) { // 还没有选择或者已经选择了两个时间
        this.removeActive(e.target.parentNode);
        e.target.classList.add('active');
        e.target.classList.add('start');
        this.setValue(new Array(new Date(parseInt(e.target.dataset.value, 10)), null));
        this.cdRef.detectChanges();
      } else if (this.value[0]) {
        const chooseDay = new Date(parseInt(e.target.dataset.value, 10)).getDate();
        const chooseMon = new Date(parseInt(e.target.dataset.value, 10)).getMonth();
        const chooseYear = new Date(parseInt(e.target.dataset.value, 10)).getFullYear();
        const valueMon = this.value[0].getMonth();
        const valueDay = this.value[0].getDate();
        const valueYear = this.value[0].getFullYear();
        if (valueDay === chooseDay && chooseMon === valueMon && chooseYear === valueYear) {
          this.removeActive(e.target.parentNode);
          this.setValue([null, null]);
          this.render();
        } else if ((chooseDay < valueDay && chooseMon === valueMon && chooseYear === valueYear)
          || (chooseMon < valueMon && chooseYear === valueYear) || chooseYear < valueYear) {
          this.removeActive(e.target.parentNode);
          e.target.classList.add('active');
          e.target.classList.add('start');
          this.setValue(new Array(new Date(parseInt(e.target.dataset.value, 10)), null));
          this.cdRef.detectChanges();
        } else {
          e.target.classList.add('active');
          e.target.classList.add('end');
          this.setValue(new Array(this.value[0], new Date(parseInt(e.target.dataset.value, 10))));
          this.render();
        }
      }
    } else if (this.tabIndex === 1) {
      if (!e.target.classList.contains('active')) {
        const value = this.parseValue(e.target.dataset.value);
        this.setValue(value);
        this.render();
      }
    } else {
      if (!e.target.classList.contains('active')) {
        const value = this.parseValue(e.target.dataset.value);
        this.setValue(value);
        this.render();
      }
    }
  }

  handleCancel() {
    this.cancel.emit();
  }

  handleClear() {
    this.setValue(new Array(2));
    this.render();
  }

  handleConfirm() {
    this.confirm.emit(this.value);
  }

  render() {
    this.el.querySelector('.date-range-picker__week-header').style.display = [0, 1].indexOf(this.tabIndex) > -1 ? '' : 'none';
    switch (this.tabIndex) {
      case 0:
        this.renderCalendar();
        break;
      case 1:
        this.renderWeekCalendar();
        break;
      case 2:
        this.renderMonth();
        break;
      case 3:
         this.renderQuarter();
         break;
    }
   /* if (this.tabIndex === 0) {
      this.renderCalendar();
    } else if (this.tabIndex === 1) {
      this.renderWeekCalendar();
    } else if (this.tabIndex === 2) {
      this.renderMonth();
    } else if (this.tabIndex === 3) {
      this.renderQuarter();
    }*/
    this.el.querySelector('.date-range-picker__month').parentNode.style.display = this.tabIndex === 2 || this.tabIndex === 3 ? 'none' : '';
  }

  getCalendarItems() {
    const result = [];
    const year = this.date.getFullYear();
    const month = this.date.getMonth();
    const lastMonthDate = this.getLastDate(year, month);
    const firstMonthDate = new Date(year, month, 1);
    const day = firstMonthDate.getDay() || 7;
    if (day !== 1) {
      for (let i = 1; i < day; i++) {
        result.unshift(new Date(firstMonthDate.getTime() - 1000 * 60 * 60 * 24 * i));
      }
    }
    for (let i = 1; i <= lastMonthDate.getDate(); i++) {
      result.push(new Date(year, month, i));
    }
    if (lastMonthDate.getDay() !== 0) {
      for (let i = 1; i <= 7 - lastMonthDate.getDay(); i++) {
        result.push(new Date(lastMonthDate.getTime() + 1000 * 60 * 60 * 24 * i));
      }
    }
    return result;
  }

  renderCalendar() {
    const year = this.date.getFullYear();
    const month = this.date.getMonth();
    const self = this;
    this.el.querySelector('.date-range-picker__calendar').innerHTML = this.getCalendarItems().map(function (item, i) {
      const value = item.getTime();
      let active = '';
      if (self.value && self.value[0] && !self.value[1] && item.getTime() === self.value[0].getTime()) {
        active = 'active start';
      }
      if (self.value && self.value[0] && self.value[1] && self.valueTabIndex
        === 0 && item.getTime() >= self.value[0].getTime() && item.getTime() <= self.value[1].getTime()) {
        active = 'active';
        if (item.getTime() === self.value[0].getTime()) {
          active += ' start';
        }
        if (item.getTime() === self.value[1].getTime()) {
          active += ' end';
        }
      }
      const outMonth = item.getMonth() !== month ? 'outmonth ' : '';
      const date = new Date();
      const now = item.getTime() === new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() ? 'now ' : '';
      return '<div class="date-range-picker__calendar-item ' + outMonth + now +
        active + ' " data-day="' + item.getDay() + '" data-value="' + value + '" data-index="' + i + '">' + item.getDate() + '</div>';
    }).join('');
  }

  renderWeekCalendar() {
    const year = this.date.getFullYear();
    const month = this.date.getMonth();
    const self = this;
    let value = '';
    this.el.querySelector('.date-range-picker__calendar').innerHTML = this.getCalendarItems().map(function (item, i) {
      if (self.tabIndex === 1 && i % 7 === 0) {
        value = item.getTime() + '-' + new Date(item.getTime() + 1000 * 60 * 60 * 24 * 6).getTime();
      }
      let active = '';
      if (self.value && self.value[0] && self.value[1] && self.valueTabIndex ===
        1 && item.getTime() >= self.value[0].getTime() && item.getTime() <= self.value[1].getTime()) {
        active = 'active';
        if (item.getTime() === self.value[0].getTime()) {
          active += ' start';
        }
        if (item.getTime() === self.value[1].getTime()) {
          active += ' end';
        }
      }
      const outMonth = item.getMonth() !== month ? 'outmonth ' : '';
      const date = new Date();
      const now = item.getTime() === new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() ? 'now ' : '';
      return '<div class="date-range-picker__calendar-item ' + outMonth + now + active +
        ' " data-day="' + item.getDay() + '" data-value="' + value + '" data-index="' + i + '">' + item.getDate() + '</div>';
    }).join('');
  }

  renderMonth() {
    const result = [];
    const self = this;
    for (let i = 0; i < 12; i++) {
      const startDate = new Date(this.date.getFullYear(), i, 1);
      const endDate = this.getLastDate(this.date.getFullYear(), i);
      let active = '';
      if (self.value && self.value[0] && self.value[1] && self.valueTabIndex ===
        2 && startDate.getTime() === self.value[0].getTime() && endDate.getTime() === self.value[1].getTime()) {
        active = 'active';
      }
      result.push('<div class="date-range-picker__calendar-month ' + active +
        '" data-value="' + startDate.getTime() + '-' + endDate.getTime() + '">' + (i + 1) + '月</div>');
    }
    this.el.querySelector('.date-range-picker__calendar').innerHTML = result.join('');
  }

  renderQuarter() {
    const result = [];
    const self = this;
    for (let i = 0; i < 4; i++) {
      const startDate = new Date(this.date.getFullYear(), i * 3, 1);
      const endDate = this.getLastDate(this.date.getFullYear(), i * 3 + 2);
      let active = '';
      if (self.value && self.value[0] && self.value[1] && self.valueTabIndex ===
        3 && startDate.getTime() === self.value[0].getTime() && endDate.getTime() === self.value[1].getTime()) {
        active = 'active';
      }
      result.push('<div class="date-range-picker__calendar-quarter ' + active +
        '" data-value="' + startDate.getTime() + '-' + endDate.getTime() + '">' + (i + 1) + '季度</div>');
    }
    this.el.querySelector('.date-range-picker__calendar').innerHTML = result.join('');
  }

  ngOnInit() {
    this.initial();
  }

}
